Skip to content

feat(manifestos): worker brief injection (#132)#142

Merged
hadamrd merged 1 commit into
trunkfrom
loop/132-feat-manifestos-worker-brief-injection-r
May 28, 2026
Merged

feat(manifestos): worker brief injection (#132)#142
hadamrd merged 1 commit into
trunkfrom
loop/132-feat-manifestos-worker-brief-injection-r

Conversation

@hadamrd
Copy link
Copy Markdown
Owner

@hadamrd hadamrd commented May 28, 2026

Summary

Inject the active quality + testing manifestos into the worker SDK system prompt so every dispatched worker reads house rules BEFORE seeing the issue body. Closes #132.

  • New forge_loop.manifestos module: discovery, rendering, sha-tagging.
  • worker.make_brief prepends a MANIFESTO block (quality first, then testing) when present.
  • WorkerOutcome gains manifesto_sha ({"quality": <sha>, "testing": <sha>} per side, None when absent).
  • Discovery happens once per dispatch in run_worker and threads into both brief + outcome (including the iteration-loop brief_override path).

Acceptance criteria → how it's tested

  • Both present → both subsections in order (quality first) — test_renders_both_manifestos_when_present, test_manifesto_block_precedes_task_brief.
  • Both missing → byte-identical pre-feature baseline — test_silent_skip_when_both_missing.
  • Only one side → that subsection only — test_partial_render_only_quality, test_partial_render_only_testing.
  • Whitespace-only → treated as missing — test_whitespace_only_manifesto_treated_as_missing, test_whitespace_only_manifesto_not_rendered_as_empty_header.
  • manifesto_sha on outcome — test_manifesto_sha_in_telemetry_both_present, test_manifesto_sha_null_when_repo_has_no_manifestos, test_manifesto_sha_partial_when_only_one_side_present.
  • Block precedes task brief — test_manifesto_block_precedes_task_brief.
  • Corrupt manifesto does not crash worker — test_corrupt_manifesto_does_not_crash_loader, test_corrupt_manifesto_does_not_crash_worker.
  • Sha matches git hash-objecttest_sha_matches_git_hash_object.

Test plan

  • pytest tests/test_worker_manifesto_injection.py — 16/16 pass
  • pytest tests/test_manifestos_discovery.py — sibling discovery tests still pass
  • ruff check clean on new files

Out of scope (per spec)

  • Critic prompt injection (follow-up ticket).
  • Per-ticket manifesto overrides / templating in bodies.
  • Dashboard surfacing of manifesto_sha.

Wire the quality + testing manifestos into the worker SDK system prompt
so every dispatched worker reads the project's house rules BEFORE it
sees the issue body. Previously, workers wrote PRs that violated rules
(missing tests, no incremental commits, ignored exit checklist) because
QUALITY.md/TESTING.md were not in-context at generation time.

What
----
- New `forge_loop.manifestos` module:
  * `load_manifestos(repo)` — discovery from `<repo>/.forge/*.md`.
    Whitespace-only files treated as missing. Unreadable / non-utf8
    files swallowed (corrupt manifesto MUST NOT crash worker).
  * `render_manifesto_block(bundle)` — formats the MANIFESTO prefix
    with `QUALITY RULES YOU MUST FOLLOW:` and `TESTING RULES YOU MUST
    FOLLOW:` subsections, quality first. Both missing → empty string
    (back-compat: byte-identical pre-feature prompt).
  * `inject_into_brief(brief, bundle)` — prepends the block ahead of
    any task-specific content.
  * Git-blob-style sha1 of each rendered file recorded for telemetry
    audit (parity-tested against `git hash-object`).

- `worker.make_brief` gains `manifesto_bundle=` kwarg and prepends
  the block when present. `WorkerOutcome` gains a `manifesto_sha`
  field (`{"quality": <sha>, "testing": <sha>}` or `None` per side).

- `run_worker` discovers the bundle once per dispatch from the repo
  checkout, threads it into both the brief renderer AND the outcome
  telemetry payload. Also wired through the iteration-loop
  `brief_override` path so round 2 sees the same rules.

Why
---
House rules drift the moment they aren't in-context. Injecting them
at the top of the system prompt frames every subsequent decision the
worker makes — including the exit-checklist + commit-discipline rules
that previously caused mid-session quits with uncommitted work.

Tests (tests/test_worker_manifesto_injection.py)
- Discovery: empty repo, both present, whitespace-only, binary garbage.
- Rendering: both, only-quality, only-testing, whitespace-as-missing.
- Injection: block precedes task-marker; empty bundle is a no-op.
- Telemetry: sha pairs round-trip on outcome for both/partial/none.
- Adversarial: corrupt manifesto → worker still dispatches, null sha.
- Sha parity: implementation matches `git hash-object` byte-for-byte.

Out of scope (per spec)
- Critic prompt injection (separate follow-up).
- Per-ticket manifesto overrides / templating in manifesto bodies.
- Dashboard surfacing of manifesto sha.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@hadamrd hadamrd merged commit f9ada94 into trunk May 28, 2026
2 checks passed
@hadamrd
Copy link
Copy Markdown
Owner Author

hadamrd commented May 28, 2026

Source issue #132 was closed mid-flight (state: closed). Loop refusing auto-merge. Reopen the issue OR merge manually.

@hadamrd hadamrd deleted the loop/132-feat-manifestos-worker-brief-injection-r branch May 28, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(manifestos): worker brief injection — render quality+testing into the system prompt

1 participant